﻿using System;
using System.IO;
using System.IO.Compression;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Runtime;
using System.Runtime.Remoting;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Serialization.Formatters.Binary;
using System.Diagnostics;
using System.Reflection;
using System.ServiceModel;

using PickGold.Callers;
using PickGold.Attributes;

namespace PickGold
{
	/// <summary>
	/// 委托调用基础类型
	/// </summary>
	[Serializable]
	[DataContract]
	[ComVisible(true)]
	[DebuggerDisplay("{_Delegate.Method}")]
	[ClassInterface(ClassInterfaceType.AutoDispatch)]
	public abstract class CDelegateBase : IDelegate
	{
		#region variables

		/// <summary>
		/// 委托返回值
		/// </summary>
		[DataMember]
		protected object _Result;

		/// <summary>
		/// 委托参数
		/// </summary>
		[DataMember]
		protected object[] _Parameters = null;

		/// <summary>
		/// 代号
		/// </summary>
		[DataMember]
		private object _CodeForSerialize = null;

		/// <summary>
		/// 代号
		/// </summary>
		[NonSerialized]
		private Guid _Code = Guid.Empty;

		/// <summary>
		/// 名称
		/// </summary>
		[DataMember]
		private string _Name = null;

		/// <summary>
		/// 用户定义的对象，它限定或包含关于委托调用的信息。
		/// </summary>
		[DataMember]
		private object _Tag = null;

		/// <summary>
		/// 委托
		/// </summary>
		[DataMember]
		private object _DelegateForSerialize = null;

		/// <summary>
		/// 委托
		/// </summary>
		[NonSerialized]
		private Delegate _Delegate = null;

		/// <summary>
		/// 另外指定执行委托的对象
		/// </summary>
		[NonSerialized]
		private object _Runner = null;

		/// <summary>
		/// 专为异步操作保存的初始句柄
		/// </summary>
		[NonSerialized]
		private ThreadStart _AsyncHandler;

		/// <summary>
		/// 专为异步操作保存的完成句柄
		/// </summary>
		[NonSerialized]
		private Dictionary<IAsyncResult, AsyncCallback> _AsyncCallbackList;

		#endregion

		/// <summary>
		/// 拷贝构造委托调用类的实例
		/// </summary>
		/// <param name="handler">要拷贝的委托调用类的实例</param>
		protected CDelegateBase(CDelegateBase handler)
		{
			handler.CopyTo(this);
		}

		/// <summary>
		/// 构造委托调用类的实例
		/// </summary>
		/// <param name="handler">需要调用的委托</param>
		protected CDelegateBase(Delegate handler)
		{
			this._Delegate = handler;
			var ls = new List<DelegateAttribute>();
			var t = this._Delegate.Method.DeclaringType.FullName;
			if (handler != null && handler.Target != null)
			{
				var p = RemotingServices.GetRealProxy(handler.Target);
				if (p != null)
				{
					var da = new DelegateAttribute(p.GetProxiedType(), true);
					ls.Add(da);
				}
			}
			var das = this._Delegate.Method.GetCustomAttributes(typeof(DelegateAttribute), false) as DelegateAttribute[];
			for (var i = 0; i < das.Length; i++)
			{
				if (DelegateAttribute.InnerNameTypeCollection[t] == null)
				{
					if (handler.Target == null)
						DelegateAttribute.InnerNameTypeCollection[t] = this._Delegate.Method.DeclaringType;
					else
						DelegateAttribute.InnerNameTypeCollection[t] = this._Delegate.Target;
				}
				if (das[i].Level <= 0)
					ls.Add(das[i]);
			}
			das = this._Delegate.Method.DeclaringType.GetCustomAttributes(typeof(DelegateAttribute), false) as DelegateAttribute[];
			for (var i = 0; i < das.Length; i++)
			{
				if (DelegateAttribute.InnerNameTypeCollection[t] == null)
				{
					if (handler.Target == null)
						DelegateAttribute.InnerNameTypeCollection[t] = this._Delegate.Method.DeclaringType;
					else
						DelegateAttribute.InnerNameTypeCollection[t] = this._Delegate.Target;
				}
				if (das[i].Level <= 0)
					ls.Add(das[i]);
			}
			if (ls.Count == 0)
			{
				this._DelegateForSerialize = this._Delegate;
				return;
			}

			t = this._Delegate.GetType().FullName +//
				Environment.NewLine + this._Delegate.Method.Name +//
				Environment.NewLine + (int)this._Delegate.Method.Attributes +//
				Environment.NewLine;
			for (var i = 0; i < ls.Count; i++)
			{
				if (string.IsNullOrEmpty(ls[i].InnerAssemblyName) && string.IsNullOrEmpty(ls[i].InnerTypeName))
				{
					ls[i].InnerAssemblyName = this._Delegate.Method.DeclaringType.Assembly.FullName;
					ls[i].InnerTypeName = this._Delegate.Method.DeclaringType.FullName;
				}
				ls[i].InnerTag = t;
			}
			this._DelegateForSerialize = ls.ToArray();
		}

		#region Async

		/// <summary>
		/// 开始一个异步委托调用
		/// </summary>
		/// <param name="callback">异步调用完成委托</param>
		/// <returns>异步操作状态</returns>
		public IAsyncResult BeginInvoke(AsyncCallback callback)
		{
			return this.BeginInvoke(callback, this);
		}

		/// <summary>
		/// 开始一个异步委托调用
		/// </summary>
		/// <param name="callback">异步调用完成委托</param>
		/// <param name="object">自定义操作状态</param>
		/// <returns>异步操作状态</returns>
		public IAsyncResult BeginInvoke(AsyncCallback callback, object @object)
		{
			if (this._AsyncHandler == null)
				this._AsyncHandler = new ThreadStart(this.InnerInvoke);
			if (this._AsyncCallbackList == null)
				this._AsyncCallbackList = new Dictionary<IAsyncResult, AsyncCallback>();
			IAsyncResult result = null;
			lock (this._AsyncCallbackList)
			{
				result = this._AsyncHandler.BeginInvoke(this.InvokeCallback, @object);
				this._AsyncCallbackList.Add(result, callback);
			}
			return result;
		}

		/// <summary>
		/// 导步委托调用结束
		/// </summary>
		/// <param name="result">异步操作状态</param>
		/// <returns>调用异常，如果成功则返回空</returns>
		public Exception EndInvoke(IAsyncResult result)
		{
			try
			{
				this._AsyncHandler.EndInvoke(result);
			}
			catch (Exception x)
			{
				Tracker.WriteError(x);
				return x;
			}

			return null;
		}

		private void InvokeCallback(IAsyncResult result)
		{
			AsyncCallback callback;
			lock (this._AsyncCallbackList)
			{
				callback = this._AsyncCallbackList[result];
				this._AsyncCallbackList.Remove(result);
			}
			if (AsyncInvoker != null && AsyncInvoker.InvokeRequired)
			{
				AsyncInvoker.Invoke(callback, result);
				return;
			}

			callback(result);
		}

		#endregion

		/// <summary>
		/// 析构
		/// </summary>
		~CDelegateBase()
		{
			this.Dispose(false);
		}

		/// <summary>
		/// 无返回调用委托
		/// </summary>
		protected virtual void InnerInvoke()
		{
			this._Result = this.Handler.Method.Invoke(this.Handler.Target, this.Parameters);
		}

		/// <summary>
		/// 委托调用
		/// </summary>
		object IDelegate.Invoke()
		{
			this.InnerInvoke();
			return this._Result;
		}

		/// <summary>
		/// 取调用有返回委托后的返回值
		/// </summary>
		object IDelegate.Result
		{
			get
			{
				return this._Result;
			}
		}

		/// <summary>
		/// 获取内部委托
		/// </summary>
		public Delegate Handler
		{
			get
			{
				if (this._Delegate != null)
					return this._Delegate;

				if (this._DelegateForSerialize == null)
					return null;

				this._Delegate = this._DelegateForSerialize as Delegate;
				if (this._Delegate != null)
					return this._Delegate;

				var das = this._DelegateForSerialize as DelegateAttribute[];
				if (das == null)
					return null;

				string t;
				string[] ts;
				Type typeD;
				Type type = null;
				string tT = null;
				string tD = null;
				var runner = this.Runner;
				for (int i = 0; i < das.Length; i++)
				{
					t = das[i].InnerTag + string.Empty;
					ts = t.Split(new char[] { '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
					if (ts.Length < 2)
						continue;

					t = das[i].InnerAssemblyName + Environment.NewLine + das[i].InnerTypeName;
					if (runner == null || (runner != this.Runner && tT != t))
					{
						runner = null;
						if (tT == t)
							continue;

						tT = t;
						try
						{
							runner = DelegateAttribute.InnerNameTypeCollection[das[i].InnerTypeName];
							if (runner != null)
							{
								type = runner as Type;
								if (type == null)
									type = runner.GetType();
								else
									runner = null;
							}
							else
							{
								type = Type.GetType(das[i].InnerTypeName, false, false);
								if (type == null)
									type = Assembly.Load(das[i].InnerAssemblyName).GetType(das[i].InnerTypeName, false, false);//load assembly.
								if (type == null)
									continue;

								DelegateAttribute.InnerNameTypeCollection[type.FullName] = type;
							}
						}
						catch
						{
							continue;//load assembly error.
						}

						if (runner == null)
						{
							runner = Reflector.GetInstance(type);//get instance
							if (runner != null)
								DelegateAttribute.InnerNameTypeCollection[type.FullName] = runner;
						}
					}//if (runner == null || (runner != this.Runner && tT != t))
					if (runner != null)
					{
						if (runner is Type)//static
							type = runner as Type;
						else
							type = runner.GetType();
					}
					else if (type != null)//static
					{
						runner = type;
					}
					else
					{
						continue;
					}

					typeD = Type.GetType(ts[0], false, true);
					//if ((MethodAttributes.Static & (MethodAttributes)int.Parse(ts[2])) == MethodAttributes.Static)
					this._Delegate = CDelegateBase.CreateDelegate(das[i], typeD, type, ts[1]);//Static
					if (this._Delegate != null)//return
						return this._Delegate;

					if (runner == null || runner is Type)//next
						continue;

					this._Delegate = CDelegateBase.CreateDelegate(das[i], typeD, runner, ts[1]);//Instance
					if (this._Delegate != null)//return
						return this._Delegate;

					if (tD != ts[0] && runner is IDelegateRunner)//get handler from interface
					{
						this._Delegate = ((IDelegateRunner)runner).GetHandler(typeD, this, ts[1], das[i].InnerTypeName, das[i].InnerAssemblyName);
						if (this._Delegate != null && this._Delegate.GetType() != typeD)
							this._Delegate = null;
					}
					if (this._Delegate != null)
						return this._Delegate;

					tT = t;
					tD = ts[0];
				}//for (int i = 0; i < das.Length; i++)
				return this._Delegate;
			}
		}

		/// <summary>
		/// 另外指定执行委托的对象
		/// </summary>
		public object Runner
		{
			set
			{
				if (!object.Equals(this._Delegate, this._DelegateForSerialize))
					this._Delegate = null;
				this._Runner = value;
			}
			get
			{
				return this._Runner;
			}
		}

		/// <summary>
		/// 取所有远程托管方法执行申明类型
		/// </summary>
		/// <returns>所有远程托管方法执行申明类型</returns>
		public Type[] GetRunnerTypes()
		{
			if (this._Delegate != null)
				return new Type[] { this._Delegate.Method.DeclaringType };

			if (this._DelegateForSerialize == null)
				return Type.EmptyTypes;

			this._Delegate = this._DelegateForSerialize as Delegate;
			if (this._Delegate != null)
				return new Type[] { this._Delegate.Method.DeclaringType };

			var das = this._DelegateForSerialize as DelegateAttribute[];
			if (das == null)
				return Type.EmptyTypes;

			var types = new List<Type>();
			foreach (var da in das)
			{
				try
				{
					types.Add(Assembly.Load(da.InnerAssemblyName).GetType(da.InnerTypeName, true, false));
				}
				catch { }
			}
			return types.ToArray();
		}

		/// <summary>
		/// 获取委托调用参数
		/// </summary>
		public object[] Parameters
		{
			get
			{
				if (this._Parameters == null || this._Parameters.Length == 0)
					return new object[] { };

				var os = new object[this._Parameters.Length];
				this._Parameters.CopyTo(os, 0);
				return os;
			}
		}

		/// <summary>
		/// 获取或设置委托调用的代号
		/// </summary>
		public Guid Code
		{
			set
			{
				this._CodeForSerialize = value;
				this._Code = value;
			}
			get
			{
				if (this._Code == Guid.Empty)
				{
					if (this._CodeForSerialize == null)
						this.Code = Guid.NewGuid();
					else
						this._Code = (Guid)this._CodeForSerialize;
				}

				return this._Code;
			}
		}

		/// <summary>
		/// 获取或设置委托调用的名称
		/// </summary>
		public string Name
		{
			set
			{
				this._Name = value;
			}
			get
			{
				if (string.IsNullOrEmpty(this._Name))
					return this.Code.ToString();

				return this._Name;
			}
		}

		/// <summary>
		/// 获取或设置用户定义的对象，它限定或包含关于委托调用的信息。
		/// </summary>
		public object Tag
		{
			set
			{
				this._Tag = value;
			}
			get
			{
				return this._Tag;
			}
		}

		/// <summary>
		/// 对象拷贝
		/// </summary>
		/// <param name="target">目标对象</param>
		/// <returns>非零值为成功</returns>
		public virtual int CopyTo(IDelegate target)
		{
			var i = 0;
			var h = target as CDelegateBase;
			if (h == null)
				return i;

			h._AsyncCallbackList = this._AsyncCallbackList;
			//i++;
			h._AsyncHandler = this._AsyncHandler;
			//i++;
			h._Code = this._Code;
			//i++;
			h._CodeForSerialize = this._CodeForSerialize;
			//i++;
			h._Delegate = this._Delegate;
			//i++;
			h._DelegateForSerialize = this._DelegateForSerialize;
			//i++;
			h._Name = this._Name;
			//i++;
			h._Parameters = this._Parameters;
			//i++;
			h._Result = this._Result;
			//i++;
			h._Runner = this._Runner;
			//i++;
			h._Tag = this._Tag;
			//i++;
			//return i;
			return 12;
		}

		/// <summary>
		/// 释放非托管资源，还可以另外再释放托管资源。
		/// </summary>
		public void Dispose()
		{
			this.Dispose(true);
		}

		/// <summary>
		/// 释放非托管资源，还可以另外再释放托管资源。
		/// </summary>
		/// <param name="disposing">是否为手动销毁对象；为 true 则释放托管资源和非托管资源；为 false 则仅释放非托管资源。</param>
		protected virtual void Dispose(bool disposing)
		{
			//if (this._IsDisposed)
			//    return;

			//this._IsDisposed = true;
			this._Result = null;
			this._Parameters = null;
			this._Delegate = null;
		}

		/// <summary>
		/// 返回表示当前 System.Object 的 System.String。
		/// </summary>
		/// <returns>System.String，表示当前的 System.Object。</returns>
		public override string ToString()
		{
			if (this._Delegate == null)
				return base.ToString();

			return this._Delegate.ToString();
		}

		private static Delegate CreateDelegate(DelegateAttribute attribute, Type handler, object target, string method)
		{
			if (handler == null || target == null || string.IsNullOrEmpty(method))
				return null;

			Delegate h;
			Type t = target as Type;
			try
			{
				if (t == null)
					h = Delegate.CreateDelegate(handler, target, method, true, false);
				else
					h = Delegate.CreateDelegate(handler, t, method, true, false);
			}
			catch
			{
				return null;
			}

			if (h == null || attribute == null)
				return h;

			if (t == null)
				t = target.GetType();
			DelegateAttribute[] das = h.Method.GetCustomAttributes(typeof(DelegateAttribute), true) as DelegateAttribute[];
			if (das != null && das.Length > 0)
			{
				for (int i = 0; i < das.Length; i++)
				{
					if (das[i].Level < 0)
						return null;

					if (das[i].Level == 0 || das[i].Level == Math.Abs(attribute.Level))
						return h;
				}

				return null;
			}

			das = t.GetCustomAttributes(typeof(DelegateAttribute), true) as DelegateAttribute[];
			if (das != null && das.Length > 0)
			{
				for (int i = 0; i < das.Length; i++)
				{
					if (das[i].Level < 0)
						return null;

					if (das[i].Level == 0 || das[i].Level == Math.Abs(attribute.Level))
						return h;
				}

				return null;
			}

			return h;
		}

		/// <summary>
		/// 异步委托调用对象，一般为窗口控件类
		/// </summary>
		public static IAsyncInvoker AsyncInvoker
		{
			set
			{
				Common.AsyncInvoker = value;
			}
			get
			{
				return Common.AsyncInvoker;
			}
		}

		#region Formatter,Serialize,Deserialize

		/// <summary>
		/// 将输入的序列化字节流数组反序列化为委托调用对象实例
		/// </summary>
		/// <param name="buffer">序列化字节流数组</param>
		/// <returns>委托调用对象实例</returns>
		public static IDelegate GetHandler(byte[] buffer)
		{
			return GetHandler(new MemoryStream(buffer), true);
		}

		/// <summary>
		/// 将输入的序列化字节流数组反序列化为委托调用对象实例
		/// </summary>
		/// <param name="buffer">序列化字节流数组</param>
		/// <param name="isZip">是否启用了压缩</param>
		/// <returns>委托调用对象实例</returns>
		public static IDelegate GetHandler(byte[] buffer, bool isZip)
		{
			return GetHandler(new MemoryStream(buffer));
		}

		/// <summary>
		/// 将输入的序列化流反序列化为委托调用对象实例
		/// </summary>
		/// <param name="stream">序列化流</param>
		/// <returns>委托调用对象实例</returns>
		public static IDelegate GetHandler(Stream stream)
		{
			return GetHandler(stream, true);
		}

		/// <summary>
		/// 将输入的序列化流反序列化为委托调用对象实例
		/// </summary>
		/// <param name="stream">序列化流</param>
		/// <param name="isZip">是否启用了压缩</param>
		/// <returns>委托调用对象实例</returns>
		public static IDelegate GetHandler(Stream stream, bool isZip)
		{
			//stream.Position = 0;
			if (!isZip)
				return new BinaryFormatter().Deserialize(stream) as IDelegate;

			GZipStream zip = new GZipStream(stream, CompressionMode.Decompress, true);
			stream = new MemoryStream();
			int i = 0;
			bool b = false;
			byte[] bs = new byte[2048];
			while (true)
			{
				i = zip.Read(bs, 0, bs.Length);
				if (i > 0)
					stream.Write(bs, 0, i);

				if (b && i == 0)
					break;

				b = true;
			}
			stream.Position = 0;
			return new BinaryFormatter().Deserialize(stream) as IDelegate;
		}

		/// <summary>
		/// 将输入的委托调用对象实例序列化为字节流数组
		/// </summary>
		/// <param name="handler">委托调用对象实例</param>
		/// <returns>序列化字节流数组</returns>
		public static byte[] GetBuffer(IDelegate handler)
		{
			return GetBuffer(handler, -1);
		}

		/// <summary>
		/// 将输入的委托调用对象实例序列化为字节流数组
		/// </summary>
		/// <param name="handler">委托调用对象实例</param>
		/// <param name="zipSize">起始压缩大小</param>
		/// <returns>序列化字节流数组</returns>
		public static byte[] GetBuffer(IDelegate handler, int zipSize)
		{
			MemoryStream stream = GetStream(handler, zipSize);
			byte[] bs = stream.ToArray();
			stream.Close();
			stream.Dispose();
			return bs;
		}

		/// <summary>
		/// 将输入的委托调用对象实例序列化为流
		/// </summary>
		/// <param name="handler">委托调用对象实例</param>
		/// <returns>序列化流</returns>
		public static MemoryStream GetStream(IDelegate handler)
		{
			return GetStream(handler, -1);
		}

		/// <summary>
		/// 将输入的委托调用对象实例序列化为流
		/// </summary>
		/// <param name="handler">委托调用对象实例</param>
		/// <param name="zipSize">起始压缩大小</param>
		/// <returns>序列化流</returns>
		public static MemoryStream GetStream(IDelegate handler, int zipSize)
		{
			BinaryFormatter binary = new BinaryFormatter();
			MemoryStream stream = new MemoryStream();
			binary.Serialize(stream, handler);
			stream.Position = 0;
			if (zipSize > stream.Length && zipSize >= 0)
				return stream;

			byte[] bs = stream.ToArray();
			stream.Close();
			stream.Dispose();
			stream = new MemoryStream();
			new GZipStream(stream, CompressionMode.Compress, true).Write(bs, 0, bs.Length);
			stream.Position = 0;
			return stream;
		}

		#endregion
	}
}
